﻿using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;

namespace CADTool.DotNetARX
{
    public static class EntTools
    {
        /// <summary>
        /// 移动实体
        /// </summary>
        /// <param name="id">实体的ObjectId</param>
        /// <param name="sourcePt">源点</param>
        /// <param name="targetPt">目标点</param>
        public static void Move(this ObjectId id, Point3d sourcePt, Point3d targetPt)
        {
            //构建用于移动实体的矩阵
            Vector3d vector = targetPt.GetVectorTo(sourcePt);
            Matrix3d mt = Matrix3d.Displacement(vector);
            //以写的方式打开id表示的实体对象
            Entity ent = (Entity)id.GetObject(OpenMode.ForWrite);
            ent.TransformBy(mt); //对实体实施移动
            ent.DowngradeOpen(); //为防止错误，切换实体为可读的状态
        }
        /// <summary>
        /// 移动实体
        /// </summary>
        /// <param name="ent">图形实体</param>
        /// <param name="sourcePt">源点</param>
        /// <param name="targetPt">目标点</param>
        public static void Move(this Entity ent, Point3d sourcePt, Point3d targetPt)
        {
            if (ent.IsNewObject) //如果是还未被添加到图形数据库的新实体
            {
                //构建用于移动实体的矩阵
                Vector3d vector = targetPt.GetVectorTo(sourcePt);
                Matrix3d mt = Matrix3d.Displacement(vector);
                ent.TransformBy(mt); //对实体实施移动
            }
            else //如果已经添加到数据库中的实体
            {
                ent.ObjectId.Move(sourcePt, targetPt);
            }
        }
        /// <summary>
        /// 复制实体
        /// </summary>
        /// <param name="id">实体的ObjectId</param>
        /// <param name="sourcePt">源点</param>
        /// <param name="targetPt">目标点</param>
        /// <returns></returns>
        public static ObjectId Copy(this ObjectId id, Point3d sourcePt, Point3d targetPt)
        {
            //构建用于复制实体的矩阵
            Vector3d vector = targetPt.GetVectorTo(sourcePt);
            Matrix3d mt = Matrix3d.Displacement(vector);
            //获取id表示实体对象
            Entity ent = (Entity)id.GetObject(OpenMode.ForRead);
            Entity entCopy = ent.GetTransformedCopy(mt);
            //将复制的对象添加到模型空间
            ObjectId copyId = id.Database.AddToModelSpace(entCopy);
            return copyId;
        }
        /// <summary>
        /// 旋转实体
        /// </summary>
        /// <param name="id">实体的ObjectId</param>
        /// <param name="basePt">旋转中心</param>
        /// <param name="angle">旋转的角度</param>
        public static void Rotate(this ObjectId id, Point3d basePt, double angle)
        {
            //angle表示旋转的角度,Axis表示旋转轴，center表示旋转中心
            Matrix3d mt = Matrix3d.Rotation(angle, Vector3d.ZAxis, basePt);
            Entity ent = (Entity)id.GetObject(OpenMode.ForRead);
            ent.TransformBy(mt);
            ent.DowngradeOpen();
        }
        /// <summary>
        /// 旋转实体
        /// </summary>
        /// <param name="id">实体的ObjectId</param>
        /// <param name="basePt">缩放基点</param>
        /// <param name="scaleFactor">缩放系数</param>
        public static void Scale(this ObjectId id, Point3d basePt, double scaleFactor)
        {
            Matrix3d mt = Matrix3d.Scaling(scaleFactor, basePt);
            Entity ent = (Entity)id.GetObject(OpenMode.ForWrite);
            ent.TransformBy(mt);
            ent.DowngradeOpen();
        }
        /// <summary>
        /// 镜像实体
        /// </summary>
        /// <param name="id">实体的ObjectId</param>
        /// <param name="mirrorPt1">镜像轴的第一点</param>
        /// <param name="mirrorPt2">镜像轴的第二点</param>
        /// <param name="eraseSourceObject">是否删除源对象</param>
        /// <returns>返回镜像实体的ObjectId</returns>
        public static ObjectId Mirror(this ObjectId id, Point3d mirrorPt1, Point3d mirrorPt2, bool eraseSourceObject)
        {
            Line3d miLine = new Line3d(mirrorPt1, mirrorPt2); //镜像线
            Matrix3d mt = Matrix3d.Mirroring(miLine);    //镜像矩阵
            ObjectId mirrorId = id;
            Entity ent = (Entity)id.GetObject(OpenMode.ForWrite);
            //如果删除源对象,则直接对原对象实施镜像变换
            if (eraseSourceObject == true)
            {
                ent.TransformBy(mt);
            }
            else
            {
                Entity entCopy = ent.GetTransformedCopy(mt);
                mirrorId = id.Database.AddToModelSpace(entCopy);
            }
            return mirrorId;
        }
        /// <summary>
        /// 偏移实体
        /// </summary>
        /// <param name="id">实体的ObjectId</param>
        /// <param name="dis">偏移的距离</param>
        /// <returns>返回偏移后的实体Id集合</returns>
        public static ObjectIdCollection Offset(this ObjectId id, double dis)
        {
            ObjectIdCollection ids = new ObjectIdCollection();
            Curve cur = id.GetObject(OpenMode.ForWrite) as Curve;
            if (cur != null)
            {
                try
                {
                    //获取偏移的对象集合
                    DBObjectCollection offsetCurves = cur.GetOffsetCurves(dis);
                    //将对象集合类型转为实体类的数组，以便加入实体操作
                    Entity[] offsetEnts = new Entity[offsetCurves.Count];
                    offsetCurves.CopyTo(offsetEnts, 0);
                    //将偏移的对象加入到数据库
                    ids = id.Database.AddToModelSpace(offsetEnts);
                }
                catch //如果发生异常
                {
                    Application.ShowAlertDialog("无法偏移！");
                }
            }
            else //如果不是曲线
            {
                Application.ShowAlertDialog("无法偏移！");
            }
            return ids; //返回偏移后的实体的Id集合
        }
        /// <summary>
        /// 矩形阵列
        /// </summary>
        /// <param name="id">实体的ObjectId</param>
        /// <param name="numRows">行数</param>
        /// <param name="numCols">列数</param>
        /// <param name="disRows">行距</param>
        /// <param name="disCols">列距</param>
        /// <returns>返回阵列后的实体集合的ObjectId</returns>
        public static ObjectIdCollection ArrayRectang(this ObjectId id, int numRows, int numCols, double disRows, double disCols)
        {
            //用于返回阵列后的实体集合的ObjectId
            ObjectIdCollection ids= new ObjectIdCollection();
            Entity ent = (Entity)id.GetObject(OpenMode.ForRead);
            for (int m = 0; m < numRows; m++)
            {
                for (int n = 0; n < numCols; n++)
                {
                    //获取平移矩阵
                    Matrix3d mt = Matrix3d.Displacement(new Vector3d(n*disCols,m*disCols,0));
                    Entity entCopy=ent.GetTransformedCopy(mt); //复制实体
                    ObjectId entCopyId=id.Database.AddToModelSpace(entCopy);
                    ids.Add(entCopyId);
                }
            }
            ent.UpgradeOpen();  //切换为写的状态
            ent.Erase();  //删除实体
            ent.DowngradeOpen(); 
            return ids; //返回阵列后的实体集合的ObjectId
        }
        /// <summary>
        /// 环形阵列
        /// </summary>
        /// <param name="id">实体的ObjectId</param>
        /// <param name="cenPt">环形阵列的中心点</param>
        /// <param name="numObj">环形阵列中要创建的对象数量</param>
        /// <param name="angle">填充角度+值表示逆时针，-值表示顺时针，角度为0出错</param>
        /// <returns>返回阵列后的实体集合的ObjectId</returns>
        public static ObjectIdCollection ArrayPolar(this ObjectId id,Point3d cenPt,int numObj,double angle)
        {
            ObjectIdCollection ids=new ObjectIdCollection();
            Entity ent=(Entity)id.GetObject(OpenMode.ForRead);
            for (int i = 0; i < numObj-1; i++)
            {
                //获取旋转矩阵
                Matrix3d mt = Matrix3d.Rotation(angle*(i+1)/numObj,Vector3d.ZAxis,cenPt);
                Entity entCopy=ent.GetTransformedCopy(mt);
                ObjectId entCopyId = id.Database.AddToModelSpace(entCopy);
                ids.Add(entCopyId);
            }
            return ids;
        }


    }
}
